const rCache = require('../model/redis_cache');
const FUN = require('../comm/func');
const mbLib = require('../comm/modbus-lib');
const devConfig = require('./devConfig');
const apiHelper = require('../comm/api-helper');

/* 实现了服务器的主要业务逻辑
 设备页面通过websocket和后台进行连接
 实现var，cmd及消息转发等数据处理业务
 */

let DebugMode = false; // 是否开启调试模式，关闭后只有来自主站的连接才被允许
let aliveDevs = new Map(); // hwid是键名，对应的连接对象是键值
// 成员：{hwid:conn}

// conn对象新增属性
// hwid 设备id，登陆时记录
// uid web链接对应的token解析的uid，暂时未用，非调试模式下要核对uid

//设备连接管理对象
module.exports = class wsDevConn
{
  static _module_name_ = 'wsDevConn';
  static mqConn = null;
  static mqPub = null;

  //信息调试
  static aliveDevs_Debug()
  {
    console.log('-------------DEBUG-------------');
    if(DebugMode) console.log('------- In Debug Mode -------');

    aliveDevs.forEach((conn,hwid)=>{
      rCache.getKey(rCache.N_Alive,hwid).then((value)=>{
        console.log(parseInt(hwid),'[VAR] '+value);
      })
    })
    console.log('-------------------------------');
  }

  //注册连接，设置了conn.hwid则表示注册成功，返回true
  static async connReg(conn,hwid,token)
  {
    if(hwid==null)
    {
      console.log('conn hwid error',hwid);
      return;
    }

    if (!DebugMode) { // 调试模式下略过
      let uInfo = await apiHelper.CheckToken(token);
      if (uInfo.uid != 0) { // 找到了用户，存储信息，定时器会处理校验
        if(aliveDevs.get(hwid) != null) aliveDevs.get(hwid).uid = uInfo.uid;
      } else { // 没有用户记录
        if(aliveDevs.get(hwid) != null) this.connUnreg(aliveDevs.get(hwid), 3015);
      }
    }

    conn.hwid=hwid;
    aliveDevs.set(hwid.toString(),conn);
    return true;
  }

  //注销连接
  static connUnreg(conn,close_code=0)
  {
    //console.log('unreg',conn.hwid);
    let hwid=conn.hwid;

    if(close_code)
      conn.close(close_code);

    if(hwid!=null)
      aliveDevs.delete(hwid.toString());
  }

  //处理客户端web页面发来的信息
  //conn连接对象
  //json信息包
  static webSocketIn(conn,json)
  {
    if(json.type == null) this.connUnreg(conn, 3016);
    if(json.type != 'info' && conn.hwid == null) this.connUnreg(conn, 3019);

    if(json.type == 'info')//登录信息，包含hwid，token
    {
      if(json.hwid==null || json.token==null || isNaN(parseInt(json.hwid)))
      {
        this.connUnreg(conn,3017);
        return;
      }

      if(aliveDevs.get(json.hwid)!=null) //return false;//每个设备只允许一个连接
      {
        console.log(parseInt(json.hwid),"webSocket 踢掉旧链接");
        this.connUnreg(aliveDevs.get(json.hwid),3018);//踢掉旧的
        this.connUnreg(conn,3018);//新的也关掉，让用户重新点开连接
        return;
      }

      console.log(parseInt(json.hwid),"webSocket 建立链接");
      this.connReg(conn,json.hwid,json.token);

      //发出retain var信息
      rCache.getKey(rCache.N_Alive,json.hwid).then((value)=>{
        if (value) this.mqMsgPass(json.hwid,'[VAR] '+value);
      })
    }
    else if(json.type=='var')//界面变量信息，json {'PKID':0,'VAR1':0,'VAR2':0,'VAR3':0}
    {
      if (json.msg!=null) devConfig.PubVar2Dev(conn.hwid, json.msg, this.mqPub);
    }
    else if(json.type=='cmd')//命令窗口信息
    {
      if (json.cmdstr!=null) devConfig.PubCmd2Dev(conn.hwid, json.cmdstr, this.mqPub);
    }
    else if(json.type=='mq')//mq消息转发
    {
      if(!json.data) return;
      if(json.crc=='1')
      {
        let crc=mbLib.crc16(json.data);
        json.data.push(crc>>8);
        json.data.push(crc&0xff);
      }
      devConfig.PubData2DevTx(conn.hwid, Buffer.from(json.data), this.mqPub);
    }
    else
    {
      this.connUnreg(conn,3019);
    }
  }

  //收到消息队列结果，转发给web客户端
  static mqMsgPass(DevId,res)
  {
    if(aliveDevs.get(DevId)) aliveDevs.get(DevId).send(res);
  }

  //广播消息
  static boardcast(msg)
  {
    server.connections.forEach((conn)=>{
      conn.send(msg);
    })
  }

  //总的mq消息处理
  //topic:srv/debug:wss 打印调试信息
  static mqMsgIn(Path,Payload,pkt)
  {
    if(Path.func=='var')
    {
      let DevIds=Path.devId.split('-');//拆分主从设备
      DevIds.forEach((hwid)=>{
        if(hwid=='0') return;
        rCache.setKey(rCache.N_Alive,hwid,Payload.toString());//记录到缓存 供网页第一次连接用
        if(pkt.retain==true) return;//不解析retain消息
        if(aliveDevs.get(hwid)==null) return;//该设备没有来自网页的链接
        this.mqMsgPass(hwid,'[VAR] '+Payload.toString());
      })
    }
    else if(Path.func=='debug')
    {
      if(Payload.toString()=='wss')
        this.aliveDevs_Debug();
    }
    else
    {
      if(aliveDevs.get(Path.devId)==null) return;
      if(Path.func=='cmdres')
      {
        this.mqMsgPass(Path.devId,Payload.toString());
      }
      else if(Path.func=='json')
      {
        try{
          let JsonStr=Payload.toString().replace(/\x00/g,'');//必须将buffer末尾的0x00去掉，否则导致JSON.parse出错
          let resObj=JSON.parse(JsonStr);
          this.mqMsgPass(Path.devId,FUN.debugObject(resObj));
        }catch(e){
          console.log('json error',e,Payload.toString());
        }
      }
      else if(Path.func=='tx')
      {
        this.mqMsgPass(Path.devId,'[TX] '+FUN.buf2Hexstr(Payload));
      }
      else if(Path.func=='rx')
      {
        this.mqMsgPass(Path.devId,'[RX] '+FUN.buf2Hexstr(Payload));
      }
    }
  }//end mqMsgIn

}//end class